﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TerhelesEloszto.Common;

namespace TerhelesEloszto.Engine
{
	public enum AssignmentStatus { ok, failed, none }

	public enum Role { user, admin, teacher, both }

	public interface IEngine
	{
		/// <summary>
		/// Visszaadja a rendszerben található tantárgyak listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszerben található tantárgyak listáját.</returns>
		List<IFact> GetFacts();

		/// <summary>
		/// Létrehoz egy új tantárgyat.
		/// </summary>
		/// <param name="name">A tárgy neve. (ne legyen üres sztring)</param>
		/// <param name="neptun">A tárgy neptun kódja. (6 karakter)</param>
		/// <param name="description">A tárgy leírása.</param>
		void CreateFact( string name, string neptun, string description );

		/// <summary>
		/// Módosít egy tantárgyat.
		/// </summary>
		/// <param name="fact">A módosítandó tárgy.</param>
		/// <param name="name">A tárgy neve. (ne legyen üres sztring) </param>
		/// <param name="description">A tárgy leírása.</param>
		void UpdateFact( IFact fact, string name, string description );

		/// <summary>
		/// Eltávolít egy tantárgyat. Minden kapcsolódó tanszéki feladat és minden ahhoz kapcsolódó információ is törlődik.
		/// </summary>
		/// <param name="fact">A törlendő tárgy.</param>
		void RemoveFact( IFact fact );

		/// <summary>
		/// Visszaadja a rendszerben található feladatok listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszerben található feladatok listáját.</returns>
		List<ITask> GetTasks();

		/// <summary>
		/// Visszaadja a rendszerben található feladatok listáját.
		/// </summary>
		/// <param name="currentSemesterOnly">True, ha csak az adott félévben érvényes taskok kellenek.</param>
		/// <returns>Visszaadja a rendszerben található feladatok listáját.</returns>
		List<ITask> GetTasks( bool currentSemesterOnly );

		/// <summary>
		/// Visszaadja a rendszerben található feladat típusok listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszerben található feladat típusok listáját.</returns>
		List<ITaskType> GetTaskTypes();

		/// <summary>
		/// Visszaadja a rendszerben található szakmai preferenciák listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszerben található szakmai preferenciák listáját.</returns>
		List<ISkill> GetSkills();

		/// <summary>
		/// Létrehoz egy új szakmai preferenciát.
		/// </summary>
		/// <param name="name">A szakmai preferencia neve. (nem lehet üres sztring).</param>
		void CreateSkill( string name );

		/// <summary>
		/// Eltávolít egy szakmai preferenciát. (És minden kapcsolódó adatot.)
		/// </summary>
		/// <param name="skill">A szakmai preferencia.</param>
		void RemoveSkill( ISkill skill );

		/// <summary>
		/// Átnevez egy szakmai prefereciát.
		/// </summary>
		/// <param name="skill">A szakmai preferencia.</param>
		/// <param name="name">Az új név. (nem lehet üres sztring.)</param>
		void RenameSkill( ISkill skill, string name );

		/// <summary>
		/// Időintervallum kontruálása a megadott paraméterekből.
		/// </summary>
		/// <param name="day">A hét napja.</param>
		/// <param name="beginHour">Az intervallum eleje. (0 és 24 közötti szám, kisebb mint az intervallum vége.)</param>
		/// <param name="endHour">Az intervallum vége. (0 és 24 közötti szám, kisebb mint az intervallum vége.)</param>
		/// <param name="parity">Páros vagy páratlan hét. (true = páratlan) </param>
		/// <returns>A megadott paraméterekből konstruált intervallum.</returns>
		IInterval ConstructInterval( DayOfWeek day, int beginHour, int endHour, bool parity );

		/// <summary>
		/// Létrehoz egy új feladatot.
		/// </summary>
		/// <param name="fact">A kapcsolódó tantárgy.</param>
		/// <param name="name">A feladat neve. (nem lehet üres sztring.)</param>
		/// <param name="type">A feladat típusa. (intervallummal rendelkező típus.)</param>
		/// <param name="skills">A szükséges szakmai preferenciák.</param>
		/// <param name="intervals">A kapcsolódó intervallumok.</param>
		/// <param name="semester">A taskhoz tartozó szemeszter</param>
		void CreateTask( IFact fact, string name, ITaskType type, List<ISkill> skills, List<IInterval> intervals, SemesterType semester );

		/// <summary>
		/// Létrehoz egy új feladatot.
		/// </summary>
		/// <param name="fact">A kapcsolódó tantárgy.</param>
		/// <param name="name">A feladat neve. (nem lehet üres szting.)</param>
		/// <param name="type">A feladat típusa. (intervallum nélküli típus.)</param>
		/// <param name="skills">A szükséges szakmai preferenciák.</param>
		/// <param name="hours">A tevékenység heti óraszáma</param>
		/// <param name="semester">A taskhoz tartozó szemeszter</param>
		void CreateTask( IFact fact, string name, ITaskType type, List<ISkill> skills, int hours, SemesterType semester );

		/// <summary>
		/// Módosít egy feladatot.
		/// </summary>
		/// <param name="task">A módosítandó feladat.</param>
		/// <param name="fact">A kapcsolódó tantárgy.</param>
		/// <param name="name">A feladat neve. (nem lehet üres sztring.)</param>
		/// <param name="type">A feladat típusa. (intervallummal rendelkező típus.)</param>
		/// <param name="skills">A szükséges szakmai preferenciák.</param>
		/// <param name="intervals">A kapcsolódó intervallumok.</param>
		/// <param name="semester">A taskhoz tartozó szemeszter</param>
		void UpdateTask( ITask task, IFact fact, string name, ITaskType type, List<ISkill> skills, List<IInterval> intervals, SemesterType semester );

		/// <summary>
		/// Módosít egy feladatot.
		/// </summary>
		/// <param name="task">A módosítandó feladat.</param>
		/// <param name="fact">A kapcsolódó tantárgy.</param>
		/// <param name="name">A feladat neve. (nem lehet üres sztring.)</param>
		/// <param name="type">A feladat típusa. (intervallum nélküli típus.)</param>
		/// <param name="skills">A szükséges szakmai preferenciák.</param>
		/// <param name="hours">A tevékenység heti óraszáma</param>
		/// <param name="semester">A taskhoz tartozó szemeszter</param>
		void UpdateTask( ITask task, IFact fact, string name, ITaskType type, List<ISkill> skills, int hours, SemesterType semester );

		/// <summary>
		/// Töröl egy feladatot. (Minden kapcsolódó információ elvész!)
		/// </summary>
		/// <param name="task">A törlendő feladat.</param>
		void RemoveTask( ITask task );

		/// <summary>
		/// Visszaadja a rendszer felhasználóinak listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszer felhasználóinak listáját.</returns>
		List<IUser> GetUsers();

		/// <summary>
		/// Visszaadja a rendszerben lévő oktatók listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszerben lévő oktatók listáját.</returns>
		List<ITeacher> GetTeachers();

		/// <summary>
		/// Visszaadja a rendszeradminisztrátorok listáját.
		/// </summary>
		/// <returns>Visszaadja a rendszeradminisztrátorok listáját.</returns>
		List<IAdmin> GetAdmins();

		/// <summary>
		/// Betölti a feladatok megjelenítéséhez és manipulálásához szükséges adatokat.
		/// </summary>
		/// <param name="facts">A tárgyak.</param>
		/// <param name="tasks">A feladatok.</param>
		/// <param name="taskTypes">A feladattípusok.</param>
		/// <param name="skills">A szakmai preferenciák.</param>
		void LoadTaskData( out List<IFact> facts, out List<ITask> tasks, out List<ITaskType> taskTypes, out List<ISkill> skills );

		/// <summary>
		/// Létrehoz egy új felhasználót.
		/// </summary>
		/// <param name="name">A felhasználó neve (nem lehet üres szting.).</param>
		/// <param name="pwHash">A felhasználó jelszavának lenyomata.</param>
		/// <param name="email">A felhasználó e-mail címe.</param>
		/// <param name="neptun">A felhasználó neptun kódja. (6 karakter)</param>
		/// <param name="isTeacher">Igaz, ha a felhasználó oktató.</param>
		/// <param name="isAdmin">Igaz, ha a felhasználó adminisztrátor.</param>
		void CreateUser( string name, int pwHash, string email, string neptun, bool isTeacher, bool isAdmin );

		/// <summary>
		/// Módosít egy felhasználót.
		/// </summary>
		/// <param name="user">A módosítandó felhasználó.</param>
		/// <param name="name">A felhasználó neve. (nem lehet üres sztring.)</param>
		/// <param name="pwHash">A felhasználó jelszavának lenyomata.</param>
		/// <param name="email">A felhasználó e-mail címe.</param>
		/// <param name="isTeacher">Igaz, ha a felhasználó oktató.</param>
		/// <param name="isAdmin">Igaz, ha a felhasználó adminisztrátor.</param>
		void UpdateUser( IUser user, string name, int pwHash, string email, bool isTeacher, bool isAdmin );

		/// <summary>
		/// Módosít egy felhasználót.
		/// </summary>
		/// <param name="user">A módosítandó felhasználó.</param>
		/// <param name="name">A felhasználó neve. (nem lehet üres sztring.)</param>
		/// <param name="pwHash">A felhasználó jelszavának lenyomata.</param>
		/// <param name="email">A felhasználó e-mail címe.</param>
		void UpdateUser( IUser user, string name, int pwHash, string email );

		/// <summary>
		/// Beállítja egy oktató szakmai és személyes preferenciáit.
		/// </summary>
		/// <param name="teacher">Az oktató.</param>
		/// <param name="skills">A szakmai preferenciák listája.</param>
		/// <param name="preferences">A személyes preferenciák listája.</param>
		void UpdatePreferences( ITeacher teacher, List<ISkill> skills, IList<ILike> preferences );

		/// <summary>
		/// Létrehoz egy személyes preferencia objektumot.
		/// </summary>
		/// <param name="target">A tantárgy.</param>
		/// <param name="stars">A csillagok száma. (minimum 0, maximum 6)</param>
		/// <returns>Létrehoz egy személyes preferencia objektumot.</returns>
		ILike ConstructLike( ITask target, int stars );

		/// <summary>
		/// Eltávolít egy felhasználót a renszerből, annak minden kapcsolódó adatával.
		/// </summary>
		/// <param name="user">Az eltávolítandó felhasználó.</param>
		void RemoveUser( IUser user );

		/// <summary>
		/// Órarend kiküldése egy oktatónak.
		/// </summary>
		/// <param name="teacher">Az oktató.</param>
		void SendTimeTable( ITeacher teacher );

		/// <summary>
		/// Órarend kiküldése minden oktatónak.
		/// </summary>
		void SendAllTimeTable();

		/// <summary>
		/// Üzenet küldése egy oktatónak.
		/// </summary>
		/// <param name="user">Az oktató.</param>
		/// <param name="message">Az üzenet.</param>
		void SendNotification( IUser user, string message );

		/// <summary>
		/// Broadcast üzenet küldése.
		/// </summary>
		/// <param name="message">Az üzenet.</param>
		/// <param name="teachersOnly">Igaz, ha csak az oktatóknak küldjük el.</param>
		/// <param name="adminsOnly">Igaz, ha csak az adminoknak küldjük el.</param>
		void SendBroadcastNotification( string message, bool teachersOnly, bool adminsOnly );

		/// <summary>
		/// Beosztás létrehozása a rendszerben lévő adatok alapján.
		/// </summary>
		/// <returns> A beosztás eredményessége.</returns>
		IAssignmentResult CreateAssignment();

		/// <summary>
		/// A beosztás jelenlegi állapotatát adja vissza.
		/// </summary>
		AssignmentStatus StatusOfAssignment { get; }

		/// <summary>
		/// Frissíti a beosztást.
		/// </summary>
		/// <param name="tasks">A feladatok listája.</param>
		void UpdateAssignment( List<ITask> tasks );

		/// <summary>
		/// Visszaadja egy oktató profilját.
		/// </summary>
		/// <param name="neptun">Az oktató neptun kódja.</param>
		/// <returns>Az oktató profilja.</returns>
		ITeacher GetTeacherProfile( string neptun );

		/// <summary>
		/// Visszaadja egy admin profilját.
		/// </summary>
		/// <param name="neptun">Az admin neptun kódja.</param>
		/// <returns>Az admin profilja.</returns>
		IAdmin GetAdminProfile( string neptun );

		/// <summary>
		/// Megpróbálja beléptetni a felhasználót.
		/// </summary>
		/// <param name="neptun">Az azonosító.</param>
		/// <param name="passwordHash">A felhasználó jelszavának lenyomata.</param>
		/// <param name="roleIsTeacher">Igaz, ha a felhasználó oktató szerepben akar belépni.</param>
		/// <returns>Igaz, ha a belépés sikeres volt.</returns>
		bool LoginUser( string neptun, int passwordHash, bool roleIsTeacher );

		/// <summary>
		/// Az oktatók szakmai profiljának szerkesztését engedélyezi vagy letiltja.
		/// </summary>		
		bool IsTeacherSettingsEnabled { get; set; }

		/// <summary>
		/// Váltás a szemeszterek között.
		/// </summary>
		void SwitchSemester();

		/// <summary>
		/// Létrehozza a jelszó lenyomatát.
		/// </summary>
		/// <param name="password">A jelszó.</param>
		/// <returns>A jelszó lenyomata.</returns>
		int CreateHash( string password );

		/// <summary>
		/// A jelenlegi szemesztert kérdezi le.
		/// </summary>
		SemesterType CurrentSemester { get; }

		/// <summary>
		/// Teszteli az üzleti logikát.
		/// </summary>
		/// <param name="nbr">A teszt sorszáma.</param>
		void Test( int nbr );

		/// <summary>
		/// Beállítja a holnapot.
		/// </summary>
		/// <param name="page">A holnap ahol az alkalmazás fut.</param>
		void SetProgramPage( string page );

		/// <summary>
		/// A megadott sztringet szemeszter típussá konvertálja.
		/// </summary>
		/// <param name="s">A sztring.</param>
		/// <returns>A szemeszter típus.</returns>
		SemesterType ConvertSemester( string s );

		/// <summary>
		/// A megadott sztringet a hét napjává konvertálja.
		/// </summary>
		/// <param name="s">A sztring.</param>
		/// <returns>A hét napja.</returns>
		DayOfWeek ConvertDay( string s );

		/// <summary>
		/// A megadott sztringet beosztás állapottá konvertálja.
		/// </summary>
		/// <param name="s">A sztring.</param>
		/// <returns>A beosztás állapota.</returns>
		AssignmentStatus ConvertStatus( string s );

		/// <summary>
		/// A megadott szemesztert szringgé alakítja.
		/// </summary>
		/// <param name="st">A szemeszter.</param>
		/// <returns>A sztring.</returns>
		string Convert( SemesterType st );

		/// <summary>
		/// A megadott napot sztringé alakítja.
		/// </summary>
		/// <param name="dow">A nap.</param>
		/// <returns>A sztring.</returns>
		string Convert( DayOfWeek dow );

		/// <summary>
		/// A megadott beosztás állapotot sztringgél alakítja.
		/// </summary>
		/// <param name="status">A beosztás állapota.</param>
		/// <returns>A sztring.</returns>
		string Convert( AssignmentStatus status );

		/// <summary>
		/// A megadott szerepet sztringgé konvertálja.
		/// </summary>
		/// <param name="r">A szerep</param>
		/// <returns>A sztring.</returns>
		string Convert( Role r );

		/// <summary>
		/// A megadott sztringet szereppé konvertálja.
		/// </summary>
		/// <param name="s">A sztring.</param>
		/// <returns>A szerep</returns>
		Role ConvertRole( string s );

		/// <summary>
		/// Igaz, ha a megadott neptunkódú felhasználónak van admin jogosultsága.
		/// </summary>
		/// <param name="s">A felhasználó neptun kódja</param>
		/// <returns>Igaz, ha a megadott neptunkódú felhasználónak van admin jogosultsága.</returns>
		bool IsAdmin( string s );

		/// <summary>
		/// Igaz, ha a megadott neptunkódú felhasználónak van oktatói jogosultsága.
		/// </summary>
		/// <param name="s">A felhasználó neptun kódja</param>
		/// <returns>Igaz, ha a megadott neptunkódú felhasználónak van oktatói jogosultsága.</returns>
		bool IsTeacher( string s );

		/// <summary>
		/// Broadcast üzenet küldése.
		/// </summary>
		/// <param name="msg">Az üzenet.</param>
		/// <param name="teachersOnly">Igaz, ha csak az oktatóknak küldjük el.</param>
		/// <param name="adminsOnly">Igaz, ha csak az adminoknak küldjük el.</param>
		void SendBroadcastNotification( MailEngine.DefaultMessage msg, bool teachersOnly, bool adminsOnly );

		/// <summary>
		/// Preferencia üzenet kiküldése egy oktatónak.
		/// </summary>
		/// <param name="teacher">Az oktató.</param>
		void SendPreferenceMessage( ITeacher teacher );

	}
}
